package com.wyg.demo.component.aspect;

import com.wyg.demo.common.CommonResult;
import com.wyg.demo.common.OperateType;
import com.wyg.demo.common.OperationResult;
import com.wyg.demo.common.ResultCode;
import com.wyg.demo.common.utils.RequestUtil;
import com.wyg.demo.domain.OperationLog;
import com.wyg.demo.service.OperationLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author ygWen
 * @Description 操作日志切面类
 * @date 2022/1/19
 */
@Slf4j
@Aspect
@Component
public class OperationLogAspect {

    @Autowired
    private HttpServletRequest httpServletRequest;
    
    @Autowired
    private OperationLogService operationLogService;
    
    public static final String POINTCUT = "execution(* com.wyg..controller..*.*(..))";
    
    @Pointcut(POINTCUT)
    public void pointcut(){}
    
    @Around("pointcut()")
    public Object insertOperationLog(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs();
        Object retValue;
        
        // 通过反射获取原方法签名
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        
        //访问路径
        String requestURI = httpServletRequest.getRequestURI();
        //IP地址
        String ipAddress = RequestUtil.getIpAddress(httpServletRequest);
        //用户id，略
        OperationLog operationLog = new OperationLog();
        operationLog.setPath(requestURI);
        operationLog.setIp(ipAddress);
        if (realMethod.isAnnotationPresent(OperateType.class)){
            OperateType operate = realMethod.getAnnotation(OperateType.class);
            //日志类型和内容
            operationLog.setType(operate.menu());
            operationLog.setContent(operate.menu() + "-" + operate.operateType());
        }
        //操作结果（ success || failure ）
        try {
            retValue = pjp.proceed(args);
            CommonResult commonResult = null;
            if (retValue instanceof CommonResult) {
                commonResult = (CommonResult) retValue;
            }
            if (commonResult != null) {
                operationLog.setResult(OperationResult.FAILURE);
                if (commonResult.getCode() == ResultCode.SUCCESS.getCode()) {
                    operationLog.setResult(OperationResult.SUCCESS);
                }
            }
        } catch (Throwable e) {
            operationLog.setResult(OperationResult.FAILURE);
            throw e;
        } finally {
            // 保存操作日志
            operationLogService.saveOperationLog(operationLog);
        }
        return retValue;
    }
}
